package org.pi.common.plot.axes

import org.pi.common.geom.Point
import org.pi.common.plot.drawables.Drawable
import org.pi.common.matrix.FloatMatrix
import org.pi.common.matrix.Api._
import org.pi.common.vision.Api._
import org.pi.common.vision.io.ImageIO

class ImageAxes(
    imageParam: FloatMatrix
  ) extends BaseXyAxes {
    override var p1: Point = Point(0,0)
    override var p2: Point = Point(1,1)
	private var image: java.awt.image.BufferedImage = null
	axesOrientation = AxesOrientation.DownRight
	setImage(imageParam)

	def this() = this(zeros(100,100))

	override def zoom(x1:Float, y1:Float,x2:Float, y2:Float) : Unit = {
    	super.zoom(Math.floor(x1.toDouble).toFloat,Math.floor(y1.toDouble).toFloat,Math.ceil(x2.toDouble).toFloat,Math.ceil(y2.toDouble).toFloat)
    }

	override protected def doAutoAdjust() {
    	super.doAutoAdjust()
	    p1 = Point(Math.min(p1.x,0),Math.min(p1.y,0))
	    p2 = Point(Math.max(p2.x,image.getWidth()),Math.max(p2.y,image.getHeight()))
    }
  	def setImage(imageParam: FloatMatrix) {
		if (imageParam.shape.length==2) {
			p1 = Point(0,0)
			p2 = Point(imageParam.length(1),imageParam.length(0))
			image = ImageIO.createBufferedImageFromGrayArray(imageParam,true,0,1)
			notifyObservers()
		}
		else if (imageParam.shape.length==3 && imageParam.length(2)==3) {
			p1 = Point(0,0)
			p2 = Point(imageParam.length(1),imageParam.length(0))
			image = ImageIO.createBufferedImageFromRgbArray(imageParam,true,0,1)
			notifyObservers()
		}
		else {
			throw new Error("unsupported image format")
		}
	}
  
  protected override def getCoordinateTransform(bounds: java.awt.Rectangle) = {
    val (factorX, factorY, offsetX, offsetY) = getXyFactorAndXyOffset(bounds.width.toFloat, bounds.height.toFloat)
    (x:Float,y:Float) =>
    ( ((x-p1.x+offsetX)*factorX) + bounds.x,
      ((y-p1.y+offsetY)*factorY) + bounds.y )
  }

  
  protected override def getInverseCoordinateTransform(bounds: java.awt.Rectangle) = {
    val (factorX, factorY, offsetX, offsetY) = getXyFactorAndXyOffset(bounds.width.toFloat, bounds.height.toFloat)
    (x:Float,y:Float) =>
    ( (x-bounds.x)/factorX +p1.x-offsetX,
      (y-bounds.y)/factorY +p1.y-offsetY )
  }

  override def paint(graphics: java.awt.Graphics2D) {
    if (autoAdjust == AxisAdjustment.Auto) doAutoAdjust
	initDefaultXTicksIfNotChangedByUser()
	initDefaultYTicksIfNotChangedByUser()

	drawAxesAndInitClipBounds(graphics)
	val f = getCoordinateTransform(graphics.getClipBounds)
    val (x0,y0) = f(0.0f,0.0f);
    val (w,h) = f(image.getWidth, image.getHeight());
    //println("0,0,w,h="+x0+" "+y0+" "+w+" "+h)
	graphics.drawImage(image,x0.toInt,y0.toInt,(w-x0).toInt,(h-y0).toInt,java.awt.Color.white,null)
    elements.foreach( e => e.draw( f, graphics) )
  }

}

object ImageAxes {
  def main(args: Array[String]) {
    import org.pi.common.plot.drawables._
    println("ImageAxes demo");
    val axes = new ImageAxes(rgb2gray(imread("data/blume2.png")))
    axes.addDrawable( new Line(0,0,100,100) )
    axes.addDrawable( new Line(-50,100,50,50) )
    AxesCanvas(axes)
    println("ImageAxes end");
  }
}